﻿using System;
using System.Collections.Generic;
using System.Linq;
using JetBrains.ProjectModel;
using JetBrains.ReSharper.Daemon;
using JetBrains.ReSharper.Daemon.Stages;
using JetBrains.ReSharper.Daemon.Xml.Highlightings;
using JetBrains.ReSharper.Psi;
using JetBrains.ReSharper.Psi.Tree;
using JetBrains.ReSharper.Psi.Xml;
using JetBrains.ReSharper.Psi.Xml.Tree;
using SPCAFContrib.Entities.Consts;
using SPCAFContrib.ReSharper.Common;
using SPCAFContrib.ReSharper.Common.Attributes;
using SPCAFContrib.ReSharper.Common.Extensions;
using SPCAFContrib.ReSharper.Common.Psi.XmlCache;
using SPCAFContrib.ReSharper.Common.Solution.ProjectFileCache;
using SPCAFContrib.ReSharper.Common.XmlAnalysis;
using SPCAFContrib.ReSharper.Inspection.Xml;
using SPCAFContrib.ReSharper.Consts;

[assembly: RegisterConfigurableSeverity(NotProvisionedEntityHighlighting.CheckId,
  null,
  Consts.CORRECTNESS_GROUP,
  NotProvisionedEntityHighlighting.CheckId + ": " + NotProvisionedEntityHighlighting.Message,
  "Any xml manifest is not included into feature consider as not provisioned.",
  Severity.ERROR,
  false, Internal = false)]

namespace SPCAFContrib.ReSharper.Inspection.Xml
{
    [Applicability(
        IDEProjectType.SP2010FarmSolution |
        IDEProjectType.SPSandbox |
        IDEProjectType.SP2013FarmSolution)]
    public class NotProvisionedEntity : XmlTagProblemAnalyzer
    {
        public override void Run(IXmlTag element, IHighlightingConsumer consumer)
        {
            if (element.GetProject().IsApplicableFor(this))
            {
                if (IsInvalid(element))
                {
                    NotProvisionedEntityHighlighting errorHighlighting =
                        new NotProvisionedEntityHighlighting(element);
                    consumer.ConsumeHighlighting(element.Header.GetDocumentRange(), errorHighlighting);
                }
            }
        }

        public static bool IsInvalid(IXmlTag element)
        {
            bool result = false;
            
            var solution = element.GetSolution();
            var project = element.GetProject();
            var sourceFile = element.GetSourceFile();
            if (sourceFile != null)
            {
                string sourceFilePath = sourceFile.GetLocation().Directory.FullPath;
                SharePointProjectItemsSolutionProvider solutionComponent =
                    solution.GetComponent<SharePointProjectItemsSolutionProvider>();
                IEnumerable<SharePointProjectItem> spProjectItems = solutionComponent.GetCacheContent(project);
                SharePointProjectItem projectItem =
                    spProjectItems.FirstOrDefault(
                        pi =>
                            pi.ElementManifest == sourceFile.Name && pi.Path == sourceFilePath);

                if (projectItem != null)
                {
                    result = !FeatureCache.GetInstance(solution)
                        .Items.Any(
                            f => f.ProjectItems.Any(pi => pi.Equals(projectItem.Id)));
                }
            }

            return result;
        }
    }

    [ConfigurableSeverityHighlighting(CheckId, XmlLanguage.Name, OverlapResolve = OverlapResolveKind.NONE, ShowToolTipInStatusBar = true)]
    public class NotProvisionedEntityHighlighting : XmlErrorHighlighting
    {
        public const string CheckId = CheckIDs.Rules.General.NotProvisionedEntity;
        public const string Message = "Not provisioned entity";

        public IXmlTag Element { get; private set; }

        public NotProvisionedEntityHighlighting(IXmlTag element) :
            base(String.Format("{0}: {1}", CheckId, Message))
        {
            Element = element;
        }

        public override bool IsValid()
        {
            return this.Element.IsValid();
        }
    }
}
